package com.wycdrive.nyc.util;

import android.content.Context;
import android.util.Log;

import com.wycdrive.nyc.main.MainActivity;
import com.wycdrive.nyc.model.api.ApiManager;
import com.wycdrive.nyc.model.vo.LocationNode;
import com.wycdrive.nyc.model.vo.ResultData;

import java.util.ArrayList;
import java.util.concurrent.TimeUnit;

import io.reactivex.Observable;
import io.reactivex.ObservableSource;
import io.reactivex.Observer;
import io.reactivex.disposables.Disposable;
import io.reactivex.functions.Function;
import io.reactivex.functions.Predicate;
import io.reactivex.schedulers.Schedulers;

public class LocationRecordUtil {
    //闲置
    public static final int IDLE = 0;
    //记录中
    public static final int RECORDING = 1;
    //停止
    public static final int STOP = 2;
    public int currentStatus = IDLE;
    private Disposable naviNodesDisposable;
    private Disposable sendistanceDisposable;
    public static String TAG = "ffffff";
    //导航经过点坐标
    private ArrayList<LocationNode> naviNodes;
    private double lastLat;
    private double lastLon;
    private Context context;
    LocationRecordListener listener;
    //118.208066,39.647447
    private double endLat = 0;
    private double endLon = 0;

    public LocationRecordUtil(Context context, LocationRecordListener listener) {
//        naviNodes = FileAndSharedPreferenceUtil.readLocations(context);
        if (naviNodes == null) {
            naviNodes = new ArrayList<>();
        }
        this.context = context;
        this.listener = listener;
    }

    public double getEndLat() {
        return endLat;
    }

    public void setEndLat(double endLat) {
        this.endLat = endLat;
    }

    public double getEndLon() {
        return endLon;
    }

    public void setEndLon(double endLon) {
        this.endLon = endLon;
    }

    public void startRecord() {
        if (currentStatus == RECORDING) {
            return;
        } else if (currentStatus == IDLE) {
            currentStatus = RECORDING;
            startRecordLocation();
        } else if (currentStatus == STOP) {
            currentStatus = RECORDING;
            startRecordLocation();
        }
        listener.onStartRecord();
    }

    public void resumeRecord() {
        if (FileAndSharedPreferenceUtil.getCurrentNaviStatus(context) == IDLE) {
        } else {
            //恢复
            // naviNodes = FileAndSharedPreferenceUtil.readLocations(context);
        }
        startRecord();

    }

    public void stopRecord() {
        if (currentStatus == RECORDING) {
            if (naviNodesDisposable != null && !naviNodesDisposable.isDisposed()) {
                naviNodesDisposable.dispose();
            }
            if (sendistanceDisposable != null && !sendistanceDisposable.isDisposed()) {
                sendistanceDisposable.dispose();
            }
            currentStatus = STOP;
            listener.onStopRecord();
        }
    }


    public void onDestory() {
        if (naviNodesDisposable != null && !naviNodesDisposable.isDisposed()) {
            naviNodesDisposable.dispose();
        }
        if (sendistanceDisposable != null && !sendistanceDisposable.isDisposed()) {
            sendistanceDisposable.dispose();
        }
        if (currentStatus == IDLE) {
            FileAndSharedPreferenceUtil.writeLocations(context, null);
            FileAndSharedPreferenceUtil.keepCurrentNaviStatus(context, IDLE);
        } else {
            // FileAndSharedPreferenceUtil.writeLocations(context, naviNodes);
            FileAndSharedPreferenceUtil.keepCurrentNaviStatus(context, currentStatus);
        }
        listener.onDestory();
    }

    //开始记录距离啦
    private void startRecordLocation() {
        naviNodes.clear();
        Observable.interval(10, TimeUnit.SECONDS).takeUntil(new Predicate<Long>() {
            @Override
            public boolean test(Long aLong) throws Exception {
                return currentStatus == STOP;
            }
        }).map(new Function<Long, LocationNode>() {
            @Override
            public LocationNode apply(Long aLong) throws Exception {
                if (LocationUtil.lat != -10000) {
                    return new LocationNode(LocationUtil.lat, LocationUtil.lon, System.currentTimeMillis());
                }
                return new LocationNode(0, 0, -1);
            }
        })
//                .distinctUntilChanged().filter(new Predicate<LocationNode>() {
//            @Override
//            public boolean test(LocationNode locationNode) throws Exception {
//                return locationNode.getCurrentTime() != -1;
//            }
//        })
                .subscribeOn(Schedulers.io()).observeOn(Schedulers.io()).subscribe(new Observer<LocationNode>() {
            @Override
            public void onSubscribe(Disposable d) {
                naviNodesDisposable = d;
            }

            @Override
            public void onNext(LocationNode node) {
                Log.d(TAG, "onNext: 加入坐标 " + node.toString());
                if (naviNodes.size() == 2) {
                    naviNodes.remove(0);
                }
                naviNodes.add(node);
                Log.d(TAG, "onNext: 坐标总数 " + naviNodes.size());
                double dis = LocationUtil.getDistance(node.getLat(), node.getLon(), endLat, endLon);
                Log.d(TAG, "距离目的地还有" + dis + "千米");
                if (dis < 0.1) {
                    Log.d(TAG, "已经到达目的地!!!!!");
                    //到达目的地
                    naviNodesDisposable.dispose();
                    currentStatus = IDLE;
                } else {
                    Log.d(TAG, "还没有到达目的地");
                }
                computeDistanceAndSendToServer();
            }

            @Override
            public void onError(Throwable e) {
                currentStatus = STOP;
            }

            @Override
            public void onComplete() {
                currentStatus = IDLE;
                //computeDistanceAndSendToServer();
            }
        });
    }

//    private void computeDistanceAndSendToServer() {
//        Log.d(TAG, "computeDistanceAndSendToServer: " + "算距离");
//        Observable.fromIterable(naviNodes).reduce(new BiFunction<LocationNode, LocationNode, LocationNode>() {
//            @Override
//            public LocationNode apply(LocationNode l1, LocationNode l2) throws Exception {
//                l2.setCurrentDistance((int) LocationUtil.getDistance(l1.getLat(), l1.getLon(), l2.getLat(), l2.getLon()));
//                return l2;
//            }
//        }).flatMapObservable(new Function<LocationNode, ObservableSource<ResultData>>() {
//            @Override
//            public ObservableSource<ResultData> apply(LocationNode locationNode) throws Exception {
//                Log.d(TAG, "当前距离" + locationNode.getCurrentDistance());
//                return ApiManager.getInstance().getDataService(MainActivity.getCookie()).sendDistance(locationNode.getCurrentDistance());
//            }
//        }).subscribeOn(Schedulers.io()).observeOn(Schedulers.io()).subscribe(new Observer<ResultData>() {
//            @Override
//            public void onSubscribe(Disposable d) {
//
//            }
//
//            @Override
//            public void onNext(ResultData o) {
//
//            }
//
//            @Override
//            public void onError(Throwable e) {
//
//            }
//
//            @Override
//            public void onComplete() {
//                Log.d(TAG, "onComplete:  成功上传距离");
//            }
//        });
//
//    }


    private void computeDistanceAndSendToServer() {
        Observable.just(naviNodes).filter(new Predicate<ArrayList<LocationNode>>() {
            @Override
            public boolean test(ArrayList<LocationNode> locationNodes) throws Exception {
                return locationNodes.size() > 1;
            }
        }).map(new Function<ArrayList<LocationNode>, Integer>() {
            @Override
            public Integer apply(ArrayList<LocationNode> locationNodes) throws Exception {
                double b = LocationUtil.getDistance(locationNodes.get(0).getLat(), locationNodes.get(0).getLon(), locationNodes.get(1).getLat(), locationNodes.get(1).getLon());
                return (int) b;
            }
        })
//                .filter(new Predicate<Integer>() {
//            @Override
//            public boolean test(Integer integer) throws Exception {
//                return integer > 0;
//            }
//        })
                .flatMap(new Function<Integer, ObservableSource<ResultData>>() {
                    @Override
                    public ObservableSource<ResultData> apply(Integer i) throws Exception {
                        return ApiManager.getInstance().getDataService(MainActivity.getCookie()).sendDistance(i, MainActivity.type, MainActivity.oid);
                    }
                }).retryWhen(new RetryWithDelay(100, 10000)).subscribeOn(Schedulers.io()).observeOn(Schedulers.io()).subscribe(new Observer<ResultData>() {
            @Override
            public void onSubscribe(Disposable d) {
                sendistanceDisposable = d;
            }

            @Override
            public void onNext(ResultData o) {

            }

            @Override
            public void onError(Throwable e) {
                Log.d(TAG, "onError: 发送距离失败");
            }

            @Override
            public void onComplete() {
                Log.d(TAG, "onError: 发送距离成功");
            }
        });

    }


}

